package wsi.gui.function;

import java.util.HashSet;
import java.util.Set;

import org.rygh.core.face.IHasName;
import org.rygh.core.face.Identifiable;
import org.rygh.gui.swing.table.STableDataModel;

import wsi.function.Function;
import wsi.function.Function.Phrase;

@SuppressWarnings("serial")
public class FunctionTableModel extends STableDataModel<FunctionMetaTuple> {

	public static final int BOOL_COL = 2;
	private static final int NOTES_COL = 3;

	private static final int ID_PRED_ROW = 5;
	private static final int NAME_PRED_ROW = 6;
	private static final int CONVERT_ROW = 9;
	public static final int INPUTS_ROW = 12;
	public static final int YAGO_ROW = 17;
	public static final int ISOMORPHIC_ROW = 19;
	public static final int RESOLVE_ROW = 21;

	private static final Set<Integer> EDITABLE_SET = new HashSet<>();

	static {
		int[] array = { 2, ID_PRED_ROW, NAME_PRED_ROW, CONVERT_ROW, INPUTS_ROW,
				13, 14, 15, 16, YAGO_ROW, 18, ISOMORPHIC_ROW, 20, RESOLVE_ROW,
				22, 23, 24 };

		for (int i : array)
			EDITABLE_SET.add(i);
	}

	private FunctionTableModel() {
		addIdColumn();
		addColumn("Key", IHasName.NAME);
		addColumn("Bool", FunctionMetaTuple.Columns.BOOL_VALUE, Boolean.class,
				40);
		addColumn("Value", Identifiable.NOTES);
	}

	public FunctionTableModel(Function function) {
		this();

		Function f = function;
		int id = 0;

		/* 0 */add(new FunctionMetaTuple(id++, "NAME", f.getName()));
		/* 1 */add(new FunctionMetaTuple(id++, "NOTE", f.getNote()));
		/* 2 */add(new FunctionMetaTuple(id++, "DIRECT", Boolean.toString(f
				.isDirect())));
		/* 3 */add(new FunctionMetaTuple(id++, "YAGO.HOP", f.getHop() + ""));
		/* 4 */add(new FunctionMetaTuple(id++, "URL", f.getUrl().getValue()));

		/* 5 */add(new FunctionMetaTuple(id++, "ID_PRED", f.getIdPredicate()));
		/* 6 */add(new FunctionMetaTuple(id++, "NAME_PRED",
				f.getNamePredicate()));
		/* 7 */add(new FunctionMetaTuple(id++, "METHOD", f.getMethod()));
		/* 8 */add(new FunctionMetaTuple(id++, "PARAMS", f.getParams()));
		/* 9 */add(new FunctionMetaTuple(id++, "CONVERT", f.getConvert()));
		/* 10 */add(new FunctionMetaTuple(id++, "OAUTH", f.getOauth()));

		/* 11 */add(new FunctionMetaTuple(id++, "FORMAT", f.getFormat()));

		/* 12 */add(new FunctionMetaTuple(id++, "SKIP.INPUT",
				Boolean.toString(f.isSkipped(Phrase.INPUT))));
		/* 13 */add(new FunctionMetaTuple(id++, "SKIP.DATA_GUIDE",
				Boolean.toString(f.isSkipped(Phrase.DATA_GUIDE))));
		/* 14 */add(new FunctionMetaTuple(id++, "SKIP.TYPE", Boolean.toString(f
				.isSkipped(Phrase.TYPE))));
		/* 15 */add(new FunctionMetaTuple(id++, "SKIP.REST", Boolean.toString(f
				.isSkipped(Phrase.REST))));
		/* 16 */add(new FunctionMetaTuple(id++, "SKIP.LOCATE_INPUT",
				Boolean.toString(f.isSkipped(Phrase.LOCATE_INPUT))));
		/* 17 */add(new FunctionMetaTuple(id++, "SKIP.YAGO_HOP",
				Boolean.toString(f.isSkipped(Phrase.YAGO_HOP))));
		/* 18 */add(new FunctionMetaTuple(id++, "SKIP.MAPPING",
				Boolean.toString(f.isSkipped(Phrase.MAPPING))));
		/* 19 */add(new FunctionMetaTuple(id++, "SKIP.FUNC_XPATH",
				Boolean.toString(f.isSkipped(Phrase.FUNC_XPATH))));
		/* 20 */add(new FunctionMetaTuple(id++, "SKIP.SUBTREE_MAPPING",
				Boolean.toString(f.isSkipped(Phrase.SUBTREE_MAPPING))));
		/* 21 */add(new FunctionMetaTuple(id++, "SKIP.RESOLVE",
				Boolean.toString(f.isSkipped(Phrase.RESOLVE))));
		/* 22 */add(new FunctionMetaTuple(id++, "SKIP.TRIPLES",
				Boolean.toString(f.isSkipped(Phrase.TRIPLES))));
		/* 23 */add(new FunctionMetaTuple(id++, "SKIP.FUNC_DEF",
				Boolean.toString(f.isSkipped(Phrase.FUNC_DEF))));
		/* 24 */add(new FunctionMetaTuple(id++, "SKIP.MEASURE",
				Boolean.toString(f.isSkipped(Phrase.MEASURE))));

		/* 25 */add(new FunctionMetaTuple(id++, "PARAMETERS", f.getParameter()
				.toString()));
	}

	@Override
	public boolean isCellEditable(int row, int col) {
		return EDITABLE_SET.contains(row) ? ((row == ID_PRED_ROW
				|| row == NAME_PRED_ROW || row == CONVERT_ROW) ? col == NOTES_COL
				: (col == BOOL_COL))
				: false;
	}

	public void reload(Function function) {
		for (int i = 0; i < getRowCount(); i++) {
			FunctionMetaTuple tuple = get(i);
			String name = tuple.getName();

			if (!name.startsWith("SKIP."))
				continue;

			name = name.substring(name.indexOf('.') + 1);
			Phrase phrase = Phrase.valueOf(name);
			tuple.setBoolValue(function.isSkipped(phrase));
		}

		fireTableDataChanged();
	}

	@Override
	public void setValueAt(Object value, int row, int col) {
		FunctionMetaTuple tuple = get(row);

		if (row != ID_PRED_ROW && row != NAME_PRED_ROW && row != CONVERT_ROW)
			tuple.setBoolValue((boolean) value);
		else
			tuple.setNotes(value.toString());

		fireTableRowsUpdated(row, row);
	}

	public void update(Function function) {
		for (int i : EDITABLE_SET) {
			FunctionMetaTuple tuple = get(i);

			if (tuple.getNotes() == null)
				continue;

			function.update(tuple.getName(), tuple.getNotes());
		}
	}

}
